<template>
  <div id="cesiumContainer"></div>
</template>

<script setup>
import {onBeforeUnmount, onMounted} from "vue";
import {Ion, Viewer, Terrain, ScreenSpaceEventHandler, ScreenSpaceEventType} from 'cesium'
import "cesium/Build/Cesium/Widgets/widgets.css";
import * as Cesium from "cesium";

// 服务器上托管 CesiumJS 静态文件的 URL。
window.CESIUM_BASE_URL = '/Cesium';
// 您的访问令牌可在以下位置找到：https://ion.cesium.com/tokens。
// 将“your_access_token”替换为您的铯离子访问令牌。
Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyNjJhZWE3NC1iYjY2LTQwZjAtODc0YS0zZTdlMjRmNTE5ZDEiLCJpZCI6MjA1NjY1LCJpYXQiOjE3MTE5MzExMzB9.efKdT634nrROZLOR-GmU5gvPmnlCDsiHDTkCYlU4SXA';

/* 创建视图（查看器） */
async function createViewer() {
  const viewer = new Viewer('cesiumContainer', {
    animation: false, // 隐藏左下角动画部件
    timeline: false, // 隐藏底部时间轴部件
    fullscreenButton: false, // 隐藏右下角全屏按钮部件
    // creditDisplay: false, // 隐藏屏幕和灯箱中显示的制作人员名单。
    geocoder: false, // 隐藏右上角搜索按钮部件
    homeButton: false, // 隐藏右上角 Home 按钮部件
    sceneModePicker: false, // 隐藏右上角场景模式按钮部件
    baseLayerPicker: false, // 隐藏右上角图层选择按钮部件
    navigationHelpButton: false, // 隐藏右上角帮助按钮部件
    vrButton: true, // 显示右下角 VRButton 按钮部件
    // selectionIndicator: false, // 隐藏点击要素之后显示的选择指示器
    // infoBox: false, // 隐藏点击要素之后显示的信息框
    // skyBox: false, // 天空盒，取消默认天空盒、太阳、月亮
    // skyAtmosphere: false, // 天空大气层，取消大气层效果 蔚蓝的天空，以及地球边缘的光芒
    // globe: false, // 要在场景中使用的地球仪。如果设置为 false ，则不会添加任何地球仪，并且默认情况下将隐藏天空大气层。
    // projectionPicker: true, // 显示右上角投影选择按钮部件
    // 所有地形提供商 - https://cesium.com/learn/cesiumjs/ref-doc/?classFilter=TerrainProvider
    terrain: Terrain.fromWorldTerrain({
      requestVertexNormals: true, // 请求其他照明信息
      requestWaterMask: true, // 请求每个磁贴的水掩码
    })
  });
  console.log('视图查看器：', viewer);
  // 启用光照
  // viewer.scene.globe.enableLighting = true;
  // 隐藏底部 Cesium logo 与 attribution 标注信息部件
  viewer.bottomContainer.style.display = 'none'
  return viewer;
}

/* 创建 Primitive 基元 - 定制几何形状与外观 */
// https://cesium.com/learn/cesiumjs/ref-doc/Primitive.html?classFilter=Primitive
function createPrimitive() {
  const instance = new Cesium.GeometryInstance({
    // 使用 id 可避免在构造基元后在内存中保留对完整实例（包括几何图形）的引用
    id: "left red rectangle",
    // 指定几何图形 - https://cesium.com/learn/cesiumjs-learn/cesiumjs-geometry-appearances/#geometry-types
    geometry: new Cesium.RectangleGeometry({
      // 指定矩形的位置
      rectangle: Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0),
      // 指定矩形的坐标系
      vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
    }),
    // 指定颜色外观
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
    }
  })

  const anotherInstance = new Cesium.GeometryInstance({
    id: "right blue rectangle",
    geometry: new Cesium.RectangleGeometry({
      rectangle: Cesium.Rectangle.fromDegrees(-85.0, 20.0, -75.0, 30.0),
      vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
    }),
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE)
    }
  });

  const primitive = new Cesium.Primitive({
    // 用于指定 Primitive 是否可见
    show: true,
    // 指定要渲染的图元
    geometryInstances: [instance, anotherInstance],
    // 用于指定 Primitive 的外观，如颜色、材质等。
    // 基元可以有多个几何实例，但只能有一个 appearance 外观。根据外观的类型，外观将具有 material 定义大部分阴影的外观。
    // https://cesium.com/learn/cesiumjs-learn/cesiumjs-geometry-appearances/#appearances
    // appearance: new Cesium.PerInstanceColorAppearance(),
    appearance: new Cesium.PerInstanceColorAppearance({
      translucent: true, // 是否开启半透明
      closed: true, // 是否开启闭合状态 - 背面剔除
      flat: true, // 是否开启平面阴影
      faceForward: true, // 翻转法线，使其始终面向观看者。避免了背面的黑色区域，例如墙壁内部。
    }),
    /*appearance: new Cesium.MaterialAppearance({
      material: Cesium.Material.fromType('Color', {
        color: Cesium.Color.RED
      })
    }),*/
    // 几何顶点针对顶点着色器前和后的缓存进行优化
    vertexCacheOptimize: true
  });
  return primitive
}

onMounted(async () => {
  let viewer = await createViewer();
  let primitive = createPrimitive(viewer);
  viewer.scene.primitives.add(primitive);

  // 添加点击事件
  let handler = new ScreenSpaceEventHandler(viewer.scene.canvas);
  handler.setInputAction(({position}) => {
    console.log(position);
    // 判断点击位置是否在矩形内
    let pick = viewer.scene.pick(position);
    if (Cesium.defined(pick) && pick.id.includes('rectangle')) {
      console.log("Mouse clicked " + pick.id);
      // 修改基元的属性 - 颜色
      // 获取对应id的基元属性
      let attributes = primitive.getGeometryInstanceAttributes(pick.id);
      // 设置随机颜色
      attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(
          Cesium.Color.fromRandom({ alpha: 1.0 })
      );
    }
  }, ScreenSpaceEventType.LEFT_CLICK)
})

onBeforeUnmount(() => {
})
</script>

<style scoped>
#cesiumContainer {
  width: 100%;
  height: 100%;
}
</style>
